package supermarket;

import java.util.Calendar;
import java.util.List;
import javax.persistence.*;
import model.*;
import model_remote.*;

public class DBmanager {
    // Πεδία
    // EntityManager για την εσωτερική Βάση Δεδομένων

    private EntityManagerFactory emf;
    private EntityManager em;
    // EntityManager για την εξωτερική Βάση Δεδομένων
    private EntityManagerFactory CCAuthorityEmf;
    private EntityManager ccem;
    // Constructor

    public DBmanager() {
        try {

            // Δημιουργία ενός EntityManagerFactory το οποίο συνδέεται στο
            // Persistence Unit που αντιστοιχεί στην Τοπική Βάση Δεδομένων
            emf = Persistence.createEntityManagerFactory("SuperMarketPU");
            // Δημιουργία ενός EntityManager
            em = emf.createEntityManager();
            // Enable query time flush at the EntityManager level:
            em.setFlushMode(FlushModeType.AUTO);
//===============================================================================
      //Η απομακρυσμένη βάση δίνει τρελό Overhead Στο startup της εφορμογής
      // γι' αυτό την ξεκινάμε σε νέο νήμα ασύχρονα απο το υπόλοιπο πρόγραμμα.
            
                 new Thread(new Runnable() {
                        @Override
                         public void run() {
                         connectRemoteDB();
                         }
                     }).start();

        } catch (Exception ex) {
            //System.out.println(ex);
            System.out.println("H Βάση δεδομένων δεν είναι ενεργή");
        }
    }

    public void connectRemoteDB() {
        // Δημιουργία ενός EntityManagerFactory το οποίο συνδέεται στο
        // Persistence Unit που αντιστοιχεί στην εξωτερική Βάση Δεδομένων
        this.CCAuthorityEmf = Persistence.createEntityManagerFactory("CREDIT_CARD_AUTH_DB");
        // Δημιουργία ενός EntityManager για την εξωτερική Βάση Δεδομένων
        this.ccem = CCAuthorityEmf.createEntityManager();
    }

    public EntityManager getEm() {
        return em;
    }

    public EntityManager getCcem() {
        return ccem;
    }

    // Η παρακάτω μέθοδος τερματίζει την σύνδεση με την Βάση Δεδομένων
    public void closeConnection() {

        try {
            // Καταστροφή του EntityManager
            em.close();
            ccem.close();
            // Καταστροφή του EntityManagerFactory
            emf.close();
            CCAuthorityEmf.close();


        } catch (Exception ex) {
            System.out.println(ex);
        }

    }

    // Καθαρίζει όλους τους πίνακες της ΒΔ
    public void clearDB() {

        try {
            em.getTransaction().begin();
            /*
             DROP TABLE  store_product;
             DROP TABLE  product_purchase;
             DROP TABLE  customer_checks;
             DROP TABLE  checks;
             DROP TABLE  purchase;
             DROP TABLE  product;
             DROP TABLE  customer;
             DROP TABLE  store;
             DROP TABLE  CREDIT_CARD;
             DROP TABLE  Bank;
             */



            Query q = em.createQuery("DELETE FROM ProductPurchase pp");
            q.executeUpdate();


            q = em.createQuery("DELETE FROM Checks p");
            q.executeUpdate();

            q = em.createQuery("DELETE FROM Product p");
            q.executeUpdate();
            q = em.createQuery("DELETE FROM Purchase pu");
            q.executeUpdate();
            q = em.createQuery("DELETE FROM Store s");
            q.executeUpdate();
            q = em.createQuery("DELETE FROM Checks c");
            q.executeUpdate();
            q = em.createQuery("DELETE FROM Customer c");
            q.executeUpdate();

            q = em.createQuery("DELETE FROM CreditCard c");
            q.executeUpdate();

            em.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }
    }

    public void createStoresAndProducts() {
        /**
         * Δημιουργεί 10 προϊόντα και 3 καταστήματα. Στη συνέχεια καθορίζει τα
         * προϊόντα που εμπορεύεται κάθε κατάστημα και τα αποθηκεύει στη ΒΔ.
         */
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            // Δημιουργία 10 διαφορετικών αντικειμένων Product.
            // public Product(Integer productId, String name, String code, int points, float price)
            Product spagheti = new Product(1, "Μακαρόνια No7", "11111", 10, 1.20f);
            Product nescafe = new Product(2, "Καφές 500gr", "22222", 12, 3.20f);
            Product cleaning = new Product(3, "Απορρυπαντικό Liquid 5lt", "33333", 20, 15.50f);
            Product oliveOil = new Product(4, "Λάδι 5lt", "44444", 6, 10.30f);
            Product bath = new Product(5, "Bath oil", "55555", 4, 6.50f);
            Product tigani = new Product(6, "Τηγάνι 30cm", "666666", 30, 20.0f);
            Product pet = new Product(7, "Pet food", "77777", 6, 9.45f);
            Product beer = new Product(8, "Beer 500mlx6", "88888", 5, 7.66f);
            Product alcoholDrink = new Product(9, "Alcohol drink", "99999", 50, 36.77f);
            Product chocolateCake = new Product(10, "Chocolate Cake", "00000", 2, 5.20f);
            // Update DB
            em.persist(spagheti);
            em.persist(nescafe);
            em.persist(cleaning);
            em.persist(oliveOil);
            em.persist(bath);
            em.persist(tigani);
            em.persist(pet);
            em.persist(beer);
            em.persist(alcoholDrink);
            em.persist(chocolateCake);
            // What em.flush() does is to empty the internal SQL instructions cache,
            // and execute it immediately to the database.
            em.flush();
            // Δημιουργία 3 διαφορετικών αντικειμένων Store.
            Store abAlimou = new Store(1, "AB Αλίμου", "Καλαμακίου 120, Άλιμος");
            Store abFalirou = new Store(2, "AB Φαλήρου", "Ποσειδώνος 300, Παλαιό Φάληρο");
            Store abParalia = new Store(3, "AB Παραλία", "Ακτή Δυμαίων 194, Στρούγκα Πάτρα");
            em.persist(abAlimou);
            em.persist(abFalirou);
            em.persist(abParalia);
            em.flush();

            // Append products to Stores
            //====abAlimou
            abAlimou.getProductList().add(spagheti);
            abAlimou.getProductList().add(cleaning);
            abAlimou.getProductList().add(nescafe);
            abAlimou.getProductList().add(oliveOil);
            abAlimou.getProductList().add(bath);
            abAlimou.getProductList().add(tigani);
            abAlimou.getProductList().add(pet);
            abAlimou.getProductList().add(chocolateCake);

            spagheti.getStoreList().add(abAlimou);
            cleaning.getStoreList().add(abAlimou);
            nescafe.getStoreList().add(abAlimou);
            oliveOil.getStoreList().add(abAlimou);
            bath.getStoreList().add(abAlimou);
            tigani.getStoreList().add(abAlimou);
            pet.getStoreList().add(abAlimou);
            chocolateCake.getStoreList().add(abAlimou);

            //====abFalirou
            abFalirou.getProductList().add(spagheti);
            abFalirou.getProductList().add(cleaning);
            abFalirou.getProductList().add(nescafe);
            abFalirou.getProductList().add(oliveOil);
            abFalirou.getProductList().add(bath);
            abFalirou.getProductList().add(beer);
            abFalirou.getProductList().add(pet);
            abFalirou.getProductList().add(alcoholDrink);

            spagheti.getStoreList().add(abFalirou);
            cleaning.getStoreList().add(abFalirou);
            nescafe.getStoreList().add(abFalirou);
            oliveOil.getStoreList().add(abFalirou);
            bath.getStoreList().add(abFalirou);
            beer.getStoreList().add(abFalirou);
            pet.getStoreList().add(abFalirou);
            alcoholDrink.getStoreList().add(abFalirou);

            //====abParalias
            abParalia.getProductList().add(spagheti);
            abParalia.getProductList().add(cleaning);
            abParalia.getProductList().add(nescafe);

            spagheti.getStoreList().add(abParalia);
            cleaning.getStoreList().add(abParalia);
            nescafe.getStoreList().add(abParalia);

            em.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }
    }

    public void createCustomersAndChecks() {
        try {

            CreditCard cc;
            Customer c;

            // First create root user (Admin)
            c = new Customer(1, "0", "0", "Master Of", "Universe", "lab", 0, true);
            this.insertCustomer(c);


            //==== Πελάτες
            //=== Αλίμονος
            c = new Customer(1, "1", "1", "Σπύρος", "Αλίμονος", "Ικονίου 35 Πάτρα", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("Σπύρος Αλίμονος");
            cc.setNumber("1234 1234 1234 1234");
            cc.setCvv(123);
            cc.setBank(this.getBankById(1));
            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                check.getCustomerList().add(c);

                //c.getChecksList().add(check);

            }
            this.updateCustomer(c);


            // create the new SEP-Customers

            //Adamos
            c = new Customer(1, "2", "2", "GEORGE", "ADAMOS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("GEORGE ADAMOS");
            cc.setNumber("1111-222111-0555");
            cc.setCvv(045);
            cc.setBank(this.getBankById(1));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);

            //====================================
            //Drossos
            c = new Customer(1, "3", "3", "NICOLAS", "DROSOS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("NICOLAS DROSOS");
            cc.setNumber("2222-333555-1234");
            cc.setCvv(667);
            cc.setBank(this.getBankById(2));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            //     for (int i = 0; i < 10; i++) {
            //        Checks check = this.newCheck();
            //        c.getChecksList().add(check);
            //         check.getCustomerList().add(c);
            //     }
            this.updateCustomer(c);
            //====================================
            //THANOS
            c = new Customer(1, "4", "4", "AGELOS", "THANOS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("AGELOS THANOS");
            cc.setNumber("3333-555322-4432");
            cc.setCvv(332);
            cc.setBank(this.getBankById(3));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================
            //KAMEAS
            c = new Customer(1, "5", "5", "ACHILEAS", "KAMEAS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("ACHILEAS KAMEAS");
            cc.setNumber("5512-332211-5544");
            cc.setCvv(332);
            cc.setBank(this.getBankById(4));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================
            //KAMEAS
            c = new Customer(1, "6", "6", "PANOS", "FITSILIS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("PANOS FITSILIS");
            cc.setNumber("6622-111542-1211");
            cc.setCvv(665);
            cc.setBank(this.getBankById(2));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================
            //ALEFRAGIS
            c = new Customer(1, "7", "7", "TAKIS", "ALEFRAGIS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("TAKIS ALEFRAGIS");
            cc.setNumber("7761-898856-8876");
            cc.setCvv(889);
            cc.setBank(this.getBankById(4));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================
            //DELIGIANNIS
            c = new Customer(1, "8", "8", "IGNATIOS", "DELIGIANNIS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("IGNATIOS DELIGIANNIS");
            cc.setNumber("9901-009211-4433");
            cc.setCvv(889);
            cc.setBank(this.getBankById(1));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================
            //BALOUKAS
            c = new Customer(1, "9", "9", "THANASIS", "BALOUKAS", "", 0, false);
            this.insertCustomer(c);

            cc = this.newCreditCard();
            cc.setOwnerName("THANASIS BALOUKAS");
            cc.setNumber("0099-981123-6655");
            cc.setCvv(390);
            cc.setBank(this.getBankById(2));

            this.updateCreditCard(cc);

            c.setCreditCard(cc);

            // Δώστου και επιταγές
            for (int i = 0; i < 10; i++) {
                Checks check = this.newCheck();
                c.getChecksList().add(check);
                check.getCustomerList().add(c);
            }
            this.updateCustomer(c);
            //====================================



        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }






    }

    public void abandonChanges(Object o) {

        em.refresh(o);
    }

    // =========  Actions In Bank Table =================
    public Bank getBankById(int id) {
        try {
            Bank b = (Bank) em.createNamedQuery("Bank.findByBankId")
                    .setParameter("bankId", id)
                    .getSingleResult();

            return b;
        } catch (Exception e) {
            return null;
        }

    }

    public List<Bank> getAllBanks() {
        try {
            List<Bank> b = em.createNamedQuery("Bank.findAll")
                    .getResultList();
            return b;
        } catch (Exception e) {
            return null;
        }
    }

// =========  Actions In Product Table =================
    public int insertProduct(Product p) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(p);
            em.getTransaction().commit();
            return 1;

        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public int deleteProduct(Product p) {
        try {
            Product p1 = getProductById(p.getProductId());
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.remove(p1);
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    public int updateProduct(Product p) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(p);
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public List getProductList() {
        try {
            List<Store> s = em.createNamedQuery("Product.findAll")
                    .getResultList();
            return s;
        } catch (Exception e) {
            return null;
        }
    }

    public Product getProductById(int id) {
        try {
            Product p = (Product) em.createNamedQuery("Product.findByProductId")
                    .setParameter("productId", id)
                    .getSingleResult();

            return p;
        } catch (Exception e) {
            return null;
        }

    }

    // =========  Actions In Customer Table =================
    public List<Customer> getAllCustomerList() {
        try {
            List<Customer> s = em.createNamedQuery("Customer.findAll")
                    .getResultList();
            return s;
        } catch (Exception e) {
            return null;
        }
    }

    public int insertCustomer(Customer c) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(c);
            em.getTransaction().commit();
            return 1;

        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public int deleteCustomer(Customer c) {
        try {
            //Διέγραψε την πιστωτική του πελάτη, αν έχει
            CreditCard cc = (CreditCard) c.getCreditCard();
            c.setCreditCard(null);
            // Διέγραψε τις επιταγές του, αν έχει
            List Checks = c.getChecksList();

            //Ksekina kai sbine
            if (cc != null) {
                this.deleteCreditCard(cc);
            }

            for (int i = 0; i < Checks.size(); i++) {
                this.deleteCheck((Checks) Checks.get(i));
                //Checks.remove(i);
            }
            //  c.getChecksList().clear();
            //update customer
            //  this.updateCustomer(c);
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            //Διέγραψε και τον πελάτη
            em.remove(c);
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    public int updateCustomer(Customer c) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(c);
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public int login(String user, String pass) {
        // return codes
        // -1 unknow user
        // -2 incorrect password
        // -3 program error
        // >0, user authenticated CustomerId returned

        try {

            List Cust = em.createNamedQuery("Customer.findByPointsCardNumber")
                    .setParameter("pointsCardNumber", user)
                    .getResultList();

            if (Cust.size() == 1) {
                Customer c = (Customer) Cust.get(0);
                if (c.getPassword().equals(pass)) {

                    return c.getCustomerId();

                } else {
                    return -2;
                }

            } else {
                return -1;
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
            return -3;
        }
    }

    public Customer getCustomerById(int id) {
        try {
            Customer c = (Customer) em.createNamedQuery("Customer.findByCustomerId")
                    .setParameter("customerId", id)
                    .getSingleResult();

            return c;
        } catch (Exception e) {
            return null;
        }

    }

    // =========  Actions In Store Table =================
    public List<Store> getStoreList() {
        try {
            List<Store> s = em.createNamedQuery("Store.findAll")
                    .getResultList();
            return s;
        } catch (Exception e) {
            return null;
        }
    }

    public Store getStoreWithID(int ID) {
        try {
            Store s = (Store) em.createNamedQuery("Store.findByStoreId")
                    .setParameter("storeId", ID)
                    .getSingleResult();
            return s;
        } catch (Exception e) {
            return null;
        }
    }

    public int updateStore(Store s) {
        try {
            Store S1 = getStoreWithID(s.getStoreId());
            S1.setName(s.getName());
            S1.setAddress(s.getAddress());

            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(S1);
            em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    // Διαγράφει ένα Store από την Βάση Δεδομένων
    public int deleteStore(Store s) {
        try {
            Store S1 = getStoreWithID(s.getStoreId());
            em.getTransaction().begin();
            em.remove(S1);
            em.getTransaction().commit();
            return 1;
        } catch (Exception ex) {
            System.out.println(ex);
            return -1;
        }
    }

    public int insertStore(Store s) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(s);
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }
    //updateStore
    // =========  Actions In CHECKS Table =================

    public Checks newCheck() {
        //get current date time with Date()
        Calendar javaCalendar = null;
        javaCalendar = Calendar.getInstance();
        String currentDate = javaCalendar.get(Calendar.DATE) + "/" + (javaCalendar.get(Calendar.MONTH) + 1) + "/" + javaCalendar.get(Calendar.YEAR);
        //Φτιάξε ένα instance Ψηεψκσ
        Checks c = new Checks(1, currentDate, true);
        //Αποθηκευσέ το στην ΒΔ.
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(c);
            em.getTransaction().commit();
            return c;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return null;
        }
    }

    public void deleteCheck(Checks c) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.remove(c);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
        }
    }

    public void updateCheck(Checks c) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(c);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
        }
    }

    // =========  Actions In CreditCard Table ==============
    public int updateCreditCard(CreditCard cc) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(cc);
            em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public CreditCard newCreditCard() {
        CreditCard cc = new CreditCard(1, 0, "", "");
        // Βάλτον σε μια τυχαία τράπεζα
        cc.setBank(this.getBankById(1));
        cc.setOwnerName("Onoma idioktiti");
        cc.setCvv(0);
        cc.setNumber("Credit Card Numer");
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(cc);
            em.getTransaction().commit();
            return cc;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return null;
        }
    }

    public void deleteCreditCard(CreditCard cc) {

        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.remove(cc);
            em.getTransaction().commit();

        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        }
    }
    // =========  Actions In Purchase Table =================

    public Purchase newPurchase(Customer c, Store s) {
        //Φτιάξε ένα instance Purchase
        //(Integer purchaseId, Date datetime, float amount, int pointsEarned, boolean delivery)
        Purchase p = new Purchase();
        p.setCustomer(c);
        p.setStore(s);
        //get current date time with Date()
        Calendar javaCalendar = null;
        javaCalendar = Calendar.getInstance();
        String currentDate = javaCalendar.get(Calendar.DATE) + "/" + (javaCalendar.get(Calendar.MONTH) + 1) + "/" + javaCalendar.get(Calendar.YEAR);
        // Update Purchase with Date
        p.setDatetime(currentDate);

        //Αποθηκευσέ το στην ΒΔ.
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(p);
            em.getTransaction().commit();
            return p;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return null;
        }
    }

    public int updatePurchase(Purchase p) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(p);
            em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public synchronized int deletePurchase(Purchase p) {
        try {
            int size = p.getProductPurchaseList().size();

            for (int i = 0; i < size; i++) {
                ProductPurchase pp = p.getProductPurchaseList().get(i);
                this.deleteProductPurchase(pp);
            }

            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.remove(p);
            //em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }
    // =========  Actions In ProductPurchase Table =================

    public ProductPurchase newProductPurchase(Product p, Purchase pur, int quantity) {
        //Φτιάξε ένα instance ProductPurchase
        ProductPurchase pp = new ProductPurchase();
        pp.setProductId(p);
        pp.setPurchaseId(pur);
        pp.setQuantity(quantity);
        //Αποθηκευσέ το στην ΒΔ.
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(pp);
            em.getTransaction().commit();
            return pp;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return null;
        }
    }

    public ProductPurchase newProductPurchase(ProductPurchase pp) {
        //Αποθηκευσέ το στην ΒΔ.
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(pp);
            em.getTransaction().commit();
            return pp;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return null;
        }
    }

    public int updateProductPurchase(ProductPurchase pp) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.persist(pp);
            em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }

    public synchronized int deleteProductPurchase(ProductPurchase pp) {
        try {
            // αρχικοποίηση transaction
            em.getTransaction().begin();
            em.remove(pp);
            em.flush();
            em.getTransaction().commit();
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
            return -1;
        }
    }
    //=============================================================================
    //=============================================================================
    //=============================================================================
    // =========  Actions In Remote DataBase ==============

    public synchronized List<CreditCardAuthority> getAllValidCreditCards() {
        try {
            List<CreditCardAuthority> cc;
            cc = ccem.createNamedQuery("CreditCardAuthority.findAll", CreditCardAuthority.class)
                    .getResultList();
            return cc;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
